<template>
  <div>
    <!-- 页面上的面包屑导航区域 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 页面上的卡片视图区域 -->
    <el-card class="box-card">
      <el-row :gutter="20">
        <!-- 搜索与删除框 -->
        <el-col :span="10">
          <el-input placeholder="请输入内容" v-model="queryInfo.query" clearable @clear="getUserList">
            <el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button>
          </el-input>
        </el-col>
        <!-- 添加用户按钮 -->
        <el-col :span="5">
          <el-button type="primary" @click="addUserDialog = true"> 添加用户 </el-button>
        </el-col>
      </el-row>
      <!-- 页面上的用户列表区域 -->
      <el-table :data="userList" border stripe>
        <el-table-column label="序号" type="index"></el-table-column>
        <el-table-column prop="username" label="姓名"></el-table-column>
        <el-table-column prop="email" label="邮箱"></el-table-column>
        <el-table-column prop="mobile" label="电话号码"></el-table-column>
        <el-table-column prop="role_name" label="角色"></el-table-column>
        <!-- ******注意：如果同时为一个模板列指定了prop和设置了作用域插槽，则作用域插槽会覆盖prop属性的值 -->
        <!-- <el-table-column prop="mg_state" label="状态"> -->
        <el-table-column label="状态">
          <template slot-scope="status">
            <!-- {{ status.row }} -->
            <!-- {{ status.row }} 的值是用户列表里每一行(每一项)的用户信息对象 -->
            <el-switch v-model="status.row.mg_state" @change="userStateChange(status.row)"></el-switch>
            <!-- ******注意：el-switch 和 status.row.mg_state 的值通过v-model双向绑定在一起了 -->
            <!-- {{ status.row.mg_state }} -->
          </template>
        </el-table-column>
        <el-table-column label="操作" width="180px">
          <template slot-scope="operate">
            <!-- 修改按钮 -->
            <el-tooltip class="item" effect="dark" content="编辑" placement="top-start" :enterable="false">
              <el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditUserDialog(operate.row)"></el-button>
            </el-tooltip>
            <!-- 删除按钮 -->
            <el-tooltip class="item" effect="dark" content="删除" placement="top-start" :enterable="false">
              <el-button type="danger" icon="el-icon-delete" size="mini" @click="showDeleteUserDialog(operate.row.id)"></el-button>
            </el-tooltip>
            <!-- 分配角色按钮 -->
            <el-tooltip class="item" effect="dark" content="分配角色" placement="top-start" :enterable="false">
              <el-button type="warning" icon="el-icon-setting" size="mini" @click="showSetRoleDialog(operate.row)"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <!-- 页面上的分页区域 -->
      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="queryInfo.pagenum" :page-sizes="[2, 5, 10]" :page-size="queryInfo.pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total"></el-pagination>
    </el-card>
    <!-- 添加用户的对话框 -->
    <!-- ***注意：dialog 可以写在任意位置 -->
    <el-dialog title="添加新用户" :visible.sync="addUserDialog" width="35%" start @close="addUserDialogClose">
      <!-- 内容主体区域 -->
      <!-- ******注意：v-model 和 prop 中的值必须相等！ -->
      <el-form :model="addUserForm" :rules="addRules" ref="addUserFormRef" label-width="70px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="addUserForm.username"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input v-model="addUserForm.password" type="password" show-password></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="addUserForm.email"></el-input>
        </el-form-item>
        <el-form-item label="手机" prop="mobile">
          <el-input v-model="addUserForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <!-- 底部区域 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="addUserDialog = false">取 消</el-button>
        <el-button type="primary" @click="addUserConfirm">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 修改用户信息的对话框 -->
    <el-dialog title="编辑用户信息" :visible.sync="editUserDialog" width="35%" start @close="closeEditUserDialog">
      <!-- 内容主体区域 -->
      <el-form :model="editUserForm" :rules="editRules" ref="editUserFormRef" label-width="70px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="editUserForm.username" disabled></el-input>
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="editUserForm.email"></el-input>
        </el-form-item>
        <el-form-item label="手机" prop="mobile">
          <el-input v-model="editUserForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <!-- 底部区域 -->
      <span slot="footer" class="dialog-footer">
        <el-button @click="editUserDialog = false">取 消</el-button>
        <el-button type="primary" @click="editUserConfirm">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 分配用户角色的对话框 -->
    <el-dialog title="分配角色" :visible.sync="setRoleDialog" width="35%" start>
      <div>
        <p>当前的用户：{{ userInfo.username }}</p>
        <p>当前的角色：{{ userInfo.role_name }}</p>
        <p>分配新角色：
          <el-select v-model="selectedRoleId" placeholder="请选择">
            <el-option v-for="item in rolesList" :key="item.id" :label="item.roleName" :value="item.id">
            </el-option>
          </el-select>
        </p>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="setRoleDialog = false">取 消</el-button>
        <el-button type="primary" @click="setRoleConfirm">确 定</el-button>
      </span>
    </el-dialog>
    <!-- test -->
    <!-- <el-button type="text" @click="open">点击打开 Message Box</el-button> -->
  </div>
</template>

<script>
export default {
  data() {
    // ******自定义邮箱和手机号的验证规则函数
    var checkEmail = (rule, value, callback) => {
      const regEmail = /^\w+@\w+(\.\w+)+$/
      if (regEmail.test(value)) {
        return callback()
      }
      // 不符合校验规则，返回一个错误提示
      callback(new Error('请输入合法的邮箱！'))
    }
    var checkPhone = (rule, value, callback) => {
      const regMobile = /^1[34578]\d{9}$/
      if (regMobile.test(value)) {
        return callback()
      }
      // 返回一个错误提示
      callback(new Error('请输入合法的手机号码！'))
    }
    return {
      // 请求用户列表数据的请求参数对象
      queryInfo: {
        // 查询参数(搜索关键字)，可以为空
        query: '',
        // 当前的页码，不能为空
        pagenum: 1,
        // 当前每页显示条数，不能为空
        pagesize: 2
      },
      userList: [],
      total: 0,
      // 控制添加用户对话框的显示/隐藏的标志位
      addUserDialog: false,
      // 控制编辑用户对话框的显示/隐藏的标志位
      editUserDialog: false,
      // 控制分配角色对话框的显示/隐藏的标志位
      setRoleDialog: false,
      // 添加新用户的表单数据
      // ***同时也是添加新用户的请求参数对象
      addUserForm: {
        username: '',
        password: '',
        email: '',
        mobile: ''
      },
      // 验证 添加用户的表单数据的 规则对象
      addRules: {
        username: [
          { required: true, message: '用户名为必填项！', trigger: 'blur' },
          { min: 2, max: 10, message: '用户名的长度应在2到10个字符之间！', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '密码为必填项！', trigger: 'blur' },
          { min: 6, max: 15, message: '密码的长度应在6到15个字符之间！', trigger: 'blur' }
        ],
        email: [
          { required: true, message: '邮箱为必填项！', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],
        mobile: [
          { required: true, message: '手机号码为必填项！', trigger: 'blur' },
          { validator: checkPhone, trigger: 'blur' }
        ]
      },
      // 查询到的用户信息对象
      // ***同时也是 发起修改用户请求 所提交的表单数据 的来源
      editUserForm: {
        id: '',
        email: '',
        mobile: ''
      },
      // 编辑用户表单 的数据的 验证规则对象
      editRules: {
        email: [
          { required: true, message: '邮箱为必填项！', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],
        mobile: [
          { required: true, message: '手机号码为必填项！', trigger: 'blur' },
          { validator: checkPhone, trigger: 'blur' }
        ]
      },
      // 当前需要被分配角色的用户的信息
      userInfo: {},
      // 请求到的所有角色的数据列表
      rolesList: [],
      // 被选中的角色的id值
      selectedRoleId: ''
    }
  },
  created() {
    this.getUserList()
  },
  methods: {
    // 获取用户列表数据
    getUserList: async function() {
      const { data: res } = await this.$xxx.get('/users', { params: this.queryInfo })
      // console.log('用户列表数据get到的data值为：')
      // console.log(res)
      if (res.meta.status !== 200) return this.$message.error('获取用户列表数据失败：' + res.meta.msg)
      // 获取用户列表数据成功，把数据保存到 data 上
      this.userList = res.data.users
      // 包含用户列表数据的数组为：
      // console.log(this.userList)
      this.total = res.data.total
    },
    // 监听分页区域 pageSize 改变的事件
    handleSizeChange: function(newPageSize) {
      // console.log(newPageSize)
      // ***注意1：pagesize不能通过this直接点出来，必须通过this->queryInfo->pagesize一层一层点出来
      this.queryInfo.pagesize = newPageSize
      // ******注意2：给pagesize赋了新的值之后，必须重新获取一遍用户列表的数据！
      this.getUserList()
    },
    // 监听分页区域 页码值 改变的事件
    handleCurrentChange: function(newPage) {
      // console.log(newPage)
      this.queryInfo.pagenum = newPage
      this.getUserList()
    },
    // 监听 用户列表中 状态一栏开关的 开启/关闭事件
    async userStateChange(userRow) {
      // console.log(userRow.id)
      // console.log(userRow.mg_state)
      // 调用接口发送修改用户状态的请求
      // ******注意：请求中的路径需要拼接动态参数，应使用模板字符串
      const res = await this.$xxx.put(`/users/${userRow.id}/state/${userRow.mg_state}`)
      // console.log(res)
      if (res.status !== 200) {
        userRow.mg_state = !userRow.mg_state
        return this.$message.error('更新用户状态失败！请稍后重试')
      }
      this.$message.success('更新用户状态成功！')
    },
    // 监听 添加用户对话框的 关闭事件
    addUserDialogClose() {
      this.$refs.addUserFormRef.resetFields()
    },
    // 监听添加用户对话框里确定按钮的点击事件
    addUserConfirm() {
      // ***预校验添加用户表单中的数据
      this.$refs.addUserFormRef.validate(async valid => {
      // console.log(valid)
        if (!valid) return
        // 预校验通过，发起添加新用户的网络请求
        const { data: res } = await this.$xxx.post('/users', this.addUserForm)
        // console.log(res)
        if (res.meta.status !== 201) return this.$message.error('添加新用户失败：' + res.meta.msg)
        this.addUserDialog = false
        // ***重新获取用户列表的数据
        this.getUserList()
        this.$message.success('添加新用户成功！')
      })
    },
    // 监听 修改用户信息对话框的 打开事件
    // ******同时获取 被点击的用户的id，再查询该用户的信息，并填充显示到与 editUserForm 双向数据绑定的 el-form 中
    async showEditUserDialog(user) {
      // 显示弹出窗
      this.editUserDialog = true
      const { data: res } = await this.$xxx.get(`users/${user.id}`)
      // console.log(res)
      if (res.meta.status !== 200) return this.$message.error('查询用户信息失败：' + res.meta.msg)
      this.editUserForm = res.data
      // console.log(this.editUserForm)
      // 将 当前要修改的信息中 用户的现有邮箱和手机号 存入 sessionStorage 中，便于后续操作
      window.sessionStorage.setItem('oldUserEmail', this.editUserForm.email)
      window.sessionStorage.setItem('oldUserMobile', this.editUserForm.mobile)
    },
    // 监听 修改用户信息对话框里 确定按钮 的点击事件
    async editUserConfirm() {
      // ***首先对表单数据进行预验证
      this.$refs.editUserFormRef.validate(async valid => {
        if (!valid) return this.$message.error('请完整填写正确的用户信息！')
        // 发送请求完成修改用户的操作
        const { data: res } = await this.$xxx.put(`users/${this.editUserForm.id}`, this.editUserForm)
        // console.log(res)
        // 从 sessionStorage 中，取出 未修改用户信息前 用户的邮箱和手机号
        const oldUserEmail = window.sessionStorage.getItem('oldUserEmail')
        const oldUserMobile = window.sessionStorage.getItem('oldUserMobile')
        if (res.meta.status !== 200) return this.$message.error('更新用户信息失败！请稍后再试')
        // 判断用户是否对用户信息做了修改
        if (res.data.email === oldUserEmail && res.data.mobile === oldUserMobile) {
          this.$message.warning('您未对用户信息做任何修改！')
          this.editUserDialog = false
          window.sessionStorage.removeItem('oldUserEmail')
          window.sessionStorage.removeItem('oldUserMobile')
          return
        }
        this.$message.success('更新用户信息成功！')
        // 关闭修改用户信息的对话框
        this.editUserDialog = false
        // 重新请求最新的数据
        this.getUserList()
        window.sessionStorage.removeItem('oldUserEmail')
        window.sessionStorage.removeItem('oldUserMobile')
      })
    },
    // 监听 修改用户信息对话框的 关闭事件
    closeEditUserDialog() {
      this.$refs.editUserFormRef.resetFields()
    },
    // 监听 删除用户 按钮的点击事件
    async showDeleteUserDialog(userid) {
      // ******弹框询问用户是否删除数据
      const confirmres = await this.$confirm('此操作将永久删除该用户, 是否继续?', '删除提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).catch(err => err)
      // console.log(confirmres)
      // 点击确定后的返回值是一个promise对象，可用async-await进行简化
      // 如果用户点击确认，则 res 的值 为'confirm'
      // 如果用户点击取消, 则 res 的值获取的就是catch的错误消息 'cancel'
      if (confirmres !== 'confirm') {
        return this.$message.info('已取消删除操作！')
      }
      const { data: res } = await this.$xxx.delete(`users/${userid}`)
      if (res.meta.status !== 200) return this.$message.error('删除用户失败！请稍后再试')
      this.$message.success('删除用户成功！')
      // 重新请求最新的数据，刷新页面
      this.getUserList()
    },
    // 监听 给用户分配角色对话框的 打开事件
    async showSetRoleDialog(user) {
      // 再每次重新打开分配角色的对话框时，先将上次被选中的角色id值清空
      this.selectedRoleId = ''
      this.userInfo = user
      // 在展示对话框之前，获取所有的角色列表的信息
      const { data: res } = await this.$xxx.get('/roles')
      if (res.meta.status !== 200) return this.$message.error('获取角色列表失败！')
      // console.log(res.data)
      this.rolesList = res.data
      this.setRoleDialog = true
    },
    // 监听 分配角色对话框中 确定按钮的点击事件
    async setRoleConfirm() {
      if (!this.selectedRoleId) return this.$message.warning('请选择要分配的新角色！')
      const { data: res } = await this.$xxx.put(`users/${this.userInfo.id}/role`, { rid: this.selectedRoleId })
      if (res.meta.status !== 200) return this.$message.error('更新角色失败：' + res.meta.msg)
      this.$message.success('更新角色成功！')
      this.setRoleDialog = false
      this.getUserList()
    }
    // test
    /* open() {
      this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$message({
          type: 'success',
          message: '删除成功!'
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    } */
  }
}
</script>

<style lang="less" scoped></style>
